home *** CD-ROM | disk | FTP | other *** search
-
-
-
- 68
-
- CHAPTER 9 - JUMPS
-
- So far we have done almost exclusively sequential programming -
- the order of execution has been from one instruction to the next
- until the very end, where the jump instruction has brought us
- back to the top. This is not the normal way programs work. In
- order to have things like DO loops, FOR loops, WHILE loops, CASE
- constructions and IF-THEN-ELSE constructs, we need to make
- decisions and to be able to go to different blocks of code
- depending on our decisions.
-
- Intel has provided a wealth of conditional jumps to answer all
- our needs. All of them are listed in a summary at the end of this
- chapter.
-
- The thing we will do most often is compare the size of two
- numbers. In BASIC code:
-
- IF A < B THEN
-
- we need to see if A < B . If that is true, we do one thing, if it
- is false, we do something else. One thing that we need to watch
- out for is whether A and B are signed or unsigned numbers. Let A
- = F523h (signed -2781; unsigned 62755) and B = 59E0h (signed
- +23008; unsigned 23008). If A and B are signed numbers, then A <
- B. However, if they are unsigned numbers, then A > B. In C and
- PASCAL, the compiler takes care of whether you want signed or
- unsigned numbers (BASIC assumes that it is always signed
- numbers). You are now on the machine level, and must take care of
- this yourself.
-
- To compare two numbers, you subtract one from the other, and then
- evaluate the result (less than 0, 0, or more than 0). To compare
- A and B, you do A minus B. To compare AX and BX, you can:
-
- sub ax, bx
-
- and then evaluate it. Unfortunately, if you do that, you will
- destroy the information in AX. It will have been changed in the
- process. Intel has solved this problem with the CMP (compare)
- instruction.
-
- cmp ax, bx
-
- subtracts BX from AX, sets the flags, and throws the answer away.
- CMP is exactly the same as SUB except that AX remains unchanged.
- We probably don't want to save the result anyway. If we do, we
- can always use:
-
- sub ax, bx
-
- We have subtracted BX from AX. There are now three possibilities.
- (1) AX > BX so the answer is positive, (2) AX = BX so the answer
- is zero, or (3) AX < BX so the answer is negative. But are these
-
- ______________________
-
- The PC Assembler Tutor - Copyright (C) 1989 Chuck Nelson
-
-
-
-
- Chapter 9 - Jumps 69
- _________________
-
- signed or unsigned numbers? The 8086 uses the same subtract (or
- CMP) instruction for both signed or unsigned numbers. You have to
- tell the 8086 in the following instruction whether you were
- talking about signed or unsigned numbers.
-
- cmp ax, bx
- ja some_label
-
- asks the machine to compare AX and BX. It then says that AX and
- BX were UNSIGNED numbers and the machine should jump to
- "some_label" if AX was above BX.
-
- cmp ax, bx
- jg some_label
-
- asks the machine to compare AX and BX. It then says that AX and
- BX were SIGNED numbers and the machine should jump to
- "some_label" if AX was greater than BX.
-
- The 8086 makes the decision by looking at the flags. They give it
- complete information about the result. (The decision making rules
- are in the summary).
-
- In our example on the previous page, we had A = -2781 (unsigned
- 62755) and B = +23008 (unsigned 23008). If we put A in AX and B
- in BX, then the instruction JA will execute the jump, while the
- instruction JG will not execute the jump. What happens if the
- 8086 doesn't execute the jump? It goes on to the next
- instruction.
-
- As I said before, the 8086 has LOTS of conditional jumps. I am
- going to give you a list of them now, but be forewarned that the
- mnemonics for these suckers are confusing. Rather than doing
- something sensible like JUG for 'jump unsigned greater' and JSG
- for 'jump signed greater' - things that would be easy to
- distinguish, they have JA for 'jump above' (unsigned) and JG for
- 'jump greater' (signed).{1} Therefore, use the summary at the
- end of the chapter. With enough use, you will remember which is
- which.
-
- The arithmetic jump instructions have two forms, a positive one
- and a negative one. For instance:
-
- ja ; jump above
- jnbe ; jump not (below or equal)
-
- are actually the same machine instruction. You use whichever one
- makes the program clearer. We will have examples later to
- illustrate both positive and negative mnemonics. Here are the
- signed and unsigned instructions and their meaning. The
- ____________________
-
- 1 This wierd use of the words above and greater, below and
- less, is so confusing that my copy of the Microsoft assembler
- manual v5.1 has it reversed on one page. It calls the signed
- jumps unsigned and the unsigned jumps signed. And that's the one
- place where it SHOULD be right.
-
-
-
-
- The PC Assembler Tutor 70
- ______________________
-
- equivalent mnemonics will appear in pairs.
-
- THESE ARE THE SIGNED JUMP INSTRUCTIONS
-
- jg ; jump if greater
- jnle ; jump if not (less or equal){2}
-
- jl ; jump if less
- jnge ; jump if not (greater or equal)
-
- je ; jump if equal
- jz ; jump if zero
-
- jge ; jump if greater or equal
- jnl ; jump if not less
-
- jle ; jump if less or equal
- jng ; jump if not greater
-
- jne ; jump if not equal
- jnz ; jump if not zero
-
- These are self-explainatory, keeping in mind that these apply
- only to signed numbers.
-
-
- THESE ARE THE UNSIGNED JUMP INSTRUCTIONS
-
- ja ; jump if above
- jnbe ; jump if not (below or equal)
-
- jb ; jump if below
- jnae ; jump if not (above or equal)
-
- je ; jump if equal
- jz ; jump if zero
-
- jae ; jump if above or equal
- jnb ; jump if not below
-
- jbe ; jump if below or equal
- jna ; jump if not above
-
- jne ; jump if not equal
- jnz ; jump if not zero
-
- These apply to unsigned numbers, and should be clear.
-
- JZ, JNZ, JE and JNE work for both signed and unsigned numbers.
- After all, zero is zero.
- ____________________
-
- 2 I was trying to decide whether or not to put in the
- parentheses. If there are two things after the "not" the "not"
- applies to both of them. By the rules of logic, not (less or
- equal) == not less AND not equal. If you don't understand this,
- try to find someone who can explain it to you.
-
-
-
-
- Chapter 9 - Jumps 71
- _________________
-
-
- Before we get going, there is one more thing you need to know.
- The unconditional jump:
-
- jmp some_label
-
- can jump anywhere in the current code segment. XXXX is the
- current number in CS, then jmp can go from XXXX offset 0 to XXXX
- offset 65535.
-
- Conditional jumps are something else entirely. ALL conditional
- jumps (including the loop instruction) are limited range jumps.
- They are from -128 to +127. That is, they can go backward up to
- 128 bytes and they can go forward up to 127 bytes.{3} You will
- find that you will get assembler errors because the conditional
- jumps are too far away, but don't worry because we can ALWAYS fix
- them. You will find out later how to deal with them.
-
-
- As in the other arithmetic instructions, there are five forms of
- the CMP instruction.
-
- 1. compare two registers
- 2. compare a register with a variable
- 3. compare a variable with a register
- 4. compare a register with a constant
- 5. compare a variable with a constant
-
- These look like:
-
- cmp ah, dl
- cmp si, memory_data
- cmp memory_data, ax
- cmp ch, 127
- cmp memory_data, 14938
-
-
- Here are some decisions we might have to make in programs.
-
- (1) We are writing a program to print hex numbers on the screen.
- We have one routine for 0 - 9 and a different one for A - F.
- Sound familiar?
-
- cmp al, 10
- jb decimal_routine
- ; here we are past the jump, so we can start the A - F
- ; routine.
-
- (2) We want to fire everyone over the age of 55 (this is an
- unsigned number since there are no negative ages):
- ____________________
-
- 3 But they don't jump from the beginning of the machine
- instruction, they jump from the END of the machine instruction
- (which is two bytes long). This means that they have an effective
- range of from -126 bytes to +129 bytes from the BEGINNING of the
- instruction.
-
-
-
-
- The PC Assembler Tutor 72
- ______________________
-
-
- cmp employee_age, 55
- ja find_a_reason_for_termination
- ; start of routine for younger employees here.
-
- (3) You want to know if you need to go to a loanshark:
-
- mov di, bank_balance
- cmp unpaid_bills, di
- jg gotta_go_see_Vinnie
- ; continue normal routine here
-
- (4) Notice that the last one could have also been written:
-
- mov di, bank_balance
- cmp di, unpaid_bills
- jl gotta_go_see_Vinnie
- ; continue normal routine
-
- though to my eye the first one seems clearer.
-
- (5) You have the results from two calculations, the first one in
- DI and the second one in CX. You need to go to different routines
- depending on which is larger. If they are the same, you exit:
-
- cmp di, cx
- jg routine_one ; di is greater
- jl routine_two ; cx is greater
- jmp exit_label ; they are equal
-
- We had two conditional jumps in a row and both of them were able
- to look at the results of the CMP instruction because the first
- jump (JG) did not change any of the flags. This is true of all
- jumps - conditional jumps, the unconditional jump, and LOOP. They
- never change any of the flags, so you can have two jumps in a row
- and be certain that the flags will not be altered.
-
-
- (6) Your dad has promised to buy you a Corvette if you don't get
- suspended from school more than three times this semester. Here's
- his decision code:
-
- cmp number_of_suspensions, 3
- jng buy_him_the_corvette
- ; better luck next time
-
-
-
- JUMP OUT OF RANGE
-
- If the code you are jumping to is more than -128 or +127 bytes
- from the end of a conditional jump, you will get an assembler
- error that the jump is out of range. This can always be fixed.
- Take this code:
-
-
-
-
-
- Chapter 9 - Jumps 73
- _________________
-
- cmp ax, bx
- jg destination_label
- further_code:
- ; continue the program
-
- If 'destination_label' is out of range, what you need to do is
- jump to 'further_code' with a conditional jump (you are within
- range of 'further_code') and use JMP (which can go anywhere in
- the segment) to go to 'destination_label'. To switch the jump,
- you simply negate the jump condition:
-
- jg -> jng
- je -> jne
- jne -> je
- jbe -> jnbe
-
- We use reverse logic. Originally, if the condition was met we
- jumped. If the condition was not met we continued. Now, if the
- condition is NOT met, we jump, and if the condition is NOT not
- met (yes, there are two NOTs) which means it was met, we
- continue, and this sends us to the JMP instruction. Make sure you
- believe this works correctly before going on. The code then looks
- like this:
-
- cmp ax, bx
- jng further_code
- jmp destination_label
- further_code:
- ; continue the program
-
- This is the standard way of handling the situation.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- The PC Assembler Tutor 74
- ______________________
-
- SUMMARY
-
- CMP
- CMP performs the same operation as subtraction, but it does
- not change the registers or variables, it only sets the flags. It
- is the cousin of TEST. As usual, there are five possibilities:
-
- 1. compare two registers
- 2. compare a register with a variable
- 3. compare a variable with a register
- 4. compare a register with a constant
- 5. compare a variable with a constant
-
-
- THESE ARE THE SIGNED JUMP INSTRUCTIONS
-
- jg ; jump if greater
- jnle ; jump if not (less or equal)
-
- jl ; jump if less
- jnge ; jump if not (greater or equal)
-
- je ; jump if equal
- jz ; jump if zero
-
- jge ; jump if greater or equal
- jnl ; jump if not less
-
- jle ; jump if less or equal
- jng ; jump if not greater
-
- jne ; jump if not equal
- jnz ; jump if not zero
-
-
-
- THESE ARE THE UNSIGNED JUMP INSTRUCTIONS
-
- ja ; jump if above
- jnbe ; jump if not (below or equal)
-
- jb ; jump if below
- jnae ; jump if not (above or equal)
-
- je ; jump if equal
- jz ; jump if zero
-
- jae ; jump if above or equal
- jnb ; jump if not below
-
- jbe ; jump if below or equal
- jna ; jump if not above
-
- jne ; jump if not equal
- jnz ; jump if not zero
-
-
-
-
-
-
- Chapter 9 - Jumps 75
- _________________
-
- THESE JUMPS CHECK A SINGLE FLAG
-
- These come in opposite pairs
-
- jc ; jump if the carry flag is set
- jnc ; jump if the carry flag is not set
-
- jo ; jump if the overflow flag is set
- jno ; jump if the overflow flag is not set
-
- jp or jpe ; jump if parity flag is set (parity is even)
- jnp or jpo ;jump if parity flag is not set (parity is odd)
-
-
- js ; jump if the sign flag is set (negative )
- jns ; jump if the sign flag is not set (positive or 0)
-
-
- THIS CHECKS THE CX REGISTER
-
- jcxz ; jump if cx is zero
-
- Why do we have this instruction? Remember, the loop instruction
- decrements CX and then checks for 0. If you enter a loop with CX
- set to zero, the loop will repeat 65536 times. Therefore, if you
- don't know what the value of CX will be when you enter the loop,
- you use this instruction just before the loop to skip the loop if
- CX is zero:
-
- jcxz after_the_loop
-
- loop_start:
- .
- .
- .
- .
- loop loop_start
- after_the_loop:
-
-
- INFORMATION ABOUT JUMPS
-
- The unconditional jump (JMP) can go anywhere in the code segment.
- All other jumps, which are conditional, can only go from -128 to
- +127 bytes from the END of the jump instruction (that's from -126
- to +129 bytes from the beginning of the instruction).
-
- Jumps have no effect on the 8086 flags.
-
- How does the 8086 decide whether something is more, less, or the
- same? The rules for unsigned numbers are easy. If you subtract a
- larger number from a smaller, the subtraction will pass through
- zero and will set the carry flag (CF). If they are the same, the
- result will be zero and it will set the zero flag (ZF). If the
- first number is larger, the machine will clear the carry flag and
- the zero flag will be cleared (ZF = 0). Therefore, for unsigned
- numbers, we have:
-
-
-
-
- The PC Assembler Tutor 76
- ______________________
-
-
- First number is:
- above CF = 0 ZF = 0
- equal CF = 0 ZF = 1
- not equal CF = ? ZF = 0
- below CF = 1 ZF = 0
-
- All other unsigned compares are combinations of those three
- things:
-
- jae = ja OR je (CF = 0 and ZF = 0) or ZF = 1
- jbe = jb OR je CF = 1 or ZF = 1
-
- When you have a negative condition, it is much easier to look at
- its equivalent positive condition to figure out what is going on:
-
- jnae is the same as jb CF = 1
- jnbe is the same as ja CF = 0 ZF = 0
-
-
- SIGNED NUMBERS
-
- This section is not for the fainthearted. It is not necessary, so
- if you find yourself getting confused, just remember that if you
- see documentation talking about a jump where the overflow flag
- equals the sign flag or the overflow flag doesn't equal the sign
- flag, it is talking about SIGNED numbers.
-
- Zero is zero, so we won't concern ourselves with it here. It is
- exactly the same.
-
- If A and B are two signed word sized numbers and we have:
-
- cmp A, B
-
- then we can have four different cases:
-
- 1) If A is just a little greater than B [(A - B) <=
- +32767], then the result will be a small positive number,
- and there will be no overflow. SF = 0, OF = 0.
-
- 2) If A is much greater than B [+32767 < (A - B)], then the
- result will be too positive and it will overflow from
- positive to negative. This will set both the sign flag (it
- is now negative) and the overflow flag. SF = 1, OF = 1.
-
- 3) If A is a little less than B [-32768 <= (A - B)], that is
- if it is only a little negative, then the result is a small
- negative number, and there is no overflow. SF = 1, OF = 0.
-
- 4) If A is much less than B [(A - B) < -32768], then the
- result is a large negative number. It is too negative and
- overflows into a positive number. SF = 0, OF = 1.
-
- Recapping, for a positive result:
-
- 1) SF = 0, OF = 0
-
-
-
-
- Chapter 9 - Jumps 77
- _________________
-
- 2) SF = 1, OF = 1
-
- and for a negative result:
-
- 3) SF = 1, OF = 0
- 4) SF = 0, OF = 1
-
- For positive results (and zero), SF = OF. For negative results,
- SF is not equal to OF. This, in fact, is how the 8086 decides a
- signed jump. If SF = OF, it's positive, if SF is not equal to OF,
- it's negative. If ZF = 1, then obviously they are equal. Here is
- the list:
-
- greater SF = OF ZF = 0
- equal SF = OF ZF = 1
- not equal ZF = 0
- less SF is not equal to OF
-
- As with the unsigned numbers, if you have a negative condition,
- it is easier to change it into its equivalent positive condition
- and then figure out the requirements. For instance:
-
- jnge same as jl SF is not equal to OF
- jnl same as jge ( SF = OF and ZF = 0 ) or ( ZF = 1)
-
- If you think about it, this OF = SF stuff does make sense. We are
- subtracting two numbers. If the first one is greater, then the
- answer will be positive. It can either be a little positive as in
- (cmp 0, -1 ) = 1 or it can be very positive, as in (cmp 32767,
- -32768) = 65,535 (same as -1). If it is just a little positive,
- there is no overflow and it has a positive sign (SF = 0, OF = 0).
- If the difference gets large, then the number overflows from + to
- -. At that point OF = 1, but it now has a negative sign, so OF =
- SF. The flags MUST match.
-
- In the opposite case where the second number is greater, The
- answer is negative. It can either be a little negative as in (cmp
- 12, 13)= -1, or it can be very negative (cmp -32768, 32767) =
- -65535 =1. If it is a small difference, the sign is negative, but
- there is no overflow (SF = 1, OF = 0). As the difference gets
- larger, the number overflows from negative to positive so the
- sign flag is now positive, but the overflow flag is set (SF = 0,
- OF = 1). Those flags CAN'T match.
-
-